using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using PickGold.Charting.Utilities;

namespace PickGold.Charting
{
	internal class CustomPropertiesTypeConverter : TypeConverter
	{
		public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
		{
			return ((sourceType == typeof(string)) || base.CanConvertFrom(context, sourceType));
		}

		public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
		{
			return ((destinationType == typeof(CustomProperties)) || base.CanConvertTo(context, destinationType));
		}

		public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
		{
			string str = value as string;
			if (((str != null) && (context != null)) && (context.Instance != null))
			{
				if (context.Instance is DataPointCustomProperties)
				{
					((DataPointCustomProperties)context.Instance).CustomProperties = str;
					return new CustomProperties((DataPointCustomProperties)context.Instance);
				}
				if (context.Instance is CustomProperties)
				{
					return new CustomProperties(((CustomProperties)context.Instance).DataPointCustomProperties);
				}
				if (context.Instance is IDataPointCustomPropertiesProvider)
				{
					return new CustomProperties(((IDataPointCustomPropertiesProvider)context.Instance).DataPointCustomProperties);
				}
				if (context.Instance is Array)
				{
					DataPointCustomProperties properties = null;
					foreach (object obj2 in (Array)context.Instance)
					{
						if (obj2 is DataPointCustomProperties)
						{
							properties = (DataPointCustomProperties)obj2;
							properties.CustomProperties = str;
						}
					}
					if (properties != null)
					{
						return new CustomProperties(properties);
					}
				}
			}
			return base.ConvertFrom(context, culture, value);
		}

		public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
		{
			if (destinationType == typeof(string))
			{
				return ((CustomProperties)value).DataPointCustomProperties.CustomProperties;
			}
			return base.ConvertTo(context, culture, value, destinationType);
		}

		public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object obj, Attribute[] attributes)
		{
			PropertyDescriptorCollection descriptors = new PropertyDescriptorCollection(null);
			CustomProperties properties = obj as CustomProperties;
			if ((properties != null) && (context != null))
			{
				Series series = (properties.DataPointCustomProperties is Series) ? ((Series)properties.DataPointCustomProperties) : properties.DataPointCustomProperties.series;
				if ((series == null) || (series.Common == null))
				{
					return descriptors;
				}
				CustomPropertyRegistry service = (CustomPropertyRegistry)series.Common.container.GetService(typeof(CustomPropertyRegistry));
				foreach (CustomPropertyInfo info in service.registeredCustomProperties)
				{
					if (this.IsApplicableCustomProperty(info, context.Instance))
					{
						Attribute[] propertyAttributes = this.GetPropertyAttributes(info);
						CustomAttributesPropertyDescriptor descriptor = new CustomAttributesPropertyDescriptor(typeof(CustomProperties), info.Name, info.ValueType, propertyAttributes, info);
						descriptors.Add(descriptor);
					}
				}
				Attribute[] attributeArray2 = new Attribute[] { new NotifyParentPropertyAttribute(true), new RefreshPropertiesAttribute(RefreshProperties.All), new DescriptionAttribute(SR.DescriptionAttributeUserDefined) };
				CustomAttributesPropertyDescriptor descriptor2 = new CustomAttributesPropertyDescriptor(typeof(CustomProperties), "UserDefined", typeof(string), attributeArray2, null);
				descriptors.Add(descriptor2);
			}
			return descriptors;
		}

		public override bool GetPropertiesSupported(ITypeDescriptorContext context)
		{
			return true;
		}

		private Attribute[] GetPropertyAttributes(CustomPropertyInfo attrInfo)
		{
			DefaultValueAttribute attribute = null;
			if (attrInfo.DefaultValue.GetType() == attrInfo.ValueType)
			{
				attribute = new DefaultValueAttribute(attrInfo.DefaultValue);
			}
			else
			{
				if (!(attrInfo.DefaultValue is string))
				{
					throw new InvalidOperationException(SR.ExceptionCustomAttributeDefaultValueTypeInvalid);
				}
				attribute = new DefaultValueAttribute(attrInfo.ValueType, (string)attrInfo.DefaultValue);
			}
			ArrayList list = new ArrayList();
			list.Add(new NotifyParentPropertyAttribute(true));
			list.Add(new RefreshPropertiesAttribute(RefreshProperties.All));
			list.Add(new DescriptionAttribute(attrInfo.Description));
			list.Add(attribute);
			int num = 0;
			Attribute[] attributeArray = new Attribute[list.Count];
			foreach (Attribute attribute2 in list)
			{
				attributeArray[num++] = attribute2;
			}
			return attributeArray;
		}

		private SeriesChartType[] GetSelectedChartTypes(object obj)
		{
			Series[] selectedSeries = this.GetSelectedSeries(obj);
			int num = 0;
			SeriesChartType[] typeArray = new SeriesChartType[selectedSeries.Length];
			foreach (Series series in selectedSeries)
			{
				typeArray[num++] = series.ChartType;
			}
			return typeArray;
		}

		private Series[] GetSelectedSeries(object obj)
		{
			Series[] array = new Series[0];
			if ((obj is Array) && (((Array)obj).Length > 0))
			{
				if (((Array)obj).GetValue(0) is Series)
				{
					array = new Series[((Array)obj).Length];
					((Array)obj).CopyTo(array, 0);
					return array;
				}
				if (((Array)obj).GetValue(0) is DataPointCustomProperties)
				{
					array = new Series[] { ((DataPointCustomProperties)((Array)obj).GetValue(0)).series };
				}
				return array;
			}
			if (obj is Series)
			{
				return new Series[] { ((Series)obj) };
			}
			if (obj is DataPointCustomProperties)
			{
				array = new Series[] { ((DataPointCustomProperties)obj).series };
			}
			return array;
		}

		private bool Is3DChartType(object obj)
		{
			foreach (Series series in this.GetSelectedSeries(obj))
			{
				ChartArea area = series.Chart.ChartAreas[series.ChartArea];
				if (area.Area3DStyle.Enable3D)
				{
					return true;
				}
			}
			return false;
		}

		private bool IsApplicableCustomProperty(CustomPropertyInfo attrInfo, object obj)
		{
			CustomProperties properties = obj as CustomProperties;
			if (properties != null)
			{
				obj = properties.DataPointCustomProperties;
			}
			if (((this.IsDataPoint(obj) && attrInfo.AppliesToDataPoint) || (!this.IsDataPoint(obj) && attrInfo.AppliesToSeries)) && ((this.Is3DChartType(obj) && attrInfo.AppliesTo3D) || (!this.Is3DChartType(obj) && attrInfo.AppliesTo2D)))
			{
				foreach (SeriesChartType type in this.GetSelectedChartTypes(obj))
				{
					foreach (SeriesChartType type2 in attrInfo.AppliesToChartType)
					{
						if (type2 == type)
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		private bool IsDataPoint(object obj)
		{
			if (obj is Series)
			{
				return false;
			}
			Array array = obj as Array;
			if (((array != null) && (array.Length > 0)) && (array.GetValue(0) is Series))
			{
				return false;
			}
			return true;
		}

		protected class CustomAttributesPropertyDescriptor : TypeConverter.SimplePropertyDescriptor
		{
			private CustomPropertyInfo _customAttributeInfo;
			private string _name;

			internal CustomAttributesPropertyDescriptor(Type componentType, string name, Type propertyType, Attribute[] attributes, CustomPropertyInfo customAttributeInfo)
				: base(componentType, name, propertyType, attributes)
			{
				this._name = string.Empty;
				this._name = name;
				this._customAttributeInfo = customAttributeInfo;
			}

			public string GetStringFromValue(object value)
			{
				if (value is Color)
				{
					ColorConverter converter = new ColorConverter();
					return converter.ConvertToString(null, CultureInfo.InvariantCulture, value);
				}
				if (value is float)
				{
					float num = (float)value;
					return num.ToString(CultureInfo.InvariantCulture);
				}
				if (value is double)
				{
					double num2 = (double)value;
					return num2.ToString(CultureInfo.InvariantCulture);
				}
				if (value is int)
				{
					int num3 = (int)value;
					return num3.ToString(CultureInfo.InvariantCulture);
				}
				if (value is bool)
				{
					bool flag = (bool)value;
					return flag.ToString();
				}
				return value.ToString();
			}

			public override object GetValue(object component)
			{
				CustomProperties properties = component as CustomProperties;
				if (this._name == "UserDefined")
				{
					return properties.GetUserDefinedCustomProperties();
				}
				string str = properties.DataPointCustomProperties[this._name];
				if (this._customAttributeInfo == null)
				{
					return str;
				}
				if ((str == null) || (str.Length == 0))
				{
					return this.GetValueFromString(this._customAttributeInfo.DefaultValue);
				}
				return this.GetValueFromString(str);
			}

			public virtual object GetValueFromString(object obj)
			{
				object obj2 = null;
				if (obj == null)
				{
					return obj2;
				}
				if (this._customAttributeInfo.ValueType == obj.GetType())
				{
					return obj;
				}
				string s = obj as string;
				if (s == null)
				{
					return obj2;
				}
				if (this._customAttributeInfo.ValueType == typeof(string))
				{
					return s;
				}
				if (this._customAttributeInfo.ValueType == typeof(float))
				{
					return float.Parse(s, CultureInfo.InvariantCulture);
				}
				if (this._customAttributeInfo.ValueType == typeof(double))
				{
					return double.Parse(s, CultureInfo.InvariantCulture);
				}
				if (this._customAttributeInfo.ValueType == typeof(int))
				{
					return int.Parse(s, CultureInfo.InvariantCulture);
				}
				if (this._customAttributeInfo.ValueType == typeof(bool))
				{
					return bool.Parse(s);
				}
				if (this._customAttributeInfo.ValueType == typeof(Color))
				{
					ColorConverter converter = new ColorConverter();
					return (Color)converter.ConvertFromString(null, CultureInfo.InvariantCulture, s);
				}
				if (!this._customAttributeInfo.ValueType.IsEnum)
				{
					throw new InvalidOperationException(SR.ExceptionCustomAttributeTypeUnsupported(this._customAttributeInfo.ValueType.ToString()));
				}
				return Enum.Parse(this._customAttributeInfo.ValueType, s, true);
			}

			public bool IsDefaultValue(string val)
			{
				string stringFromValue = this.GetStringFromValue(this._customAttributeInfo.DefaultValue);
				return (string.Compare(val, stringFromValue, StringComparison.Ordinal) == 0);
			}

			public override void SetValue(object component, object value)
			{
				this.ValidateValue(this._name, value);
				string stringFromValue = this.GetStringFromValue(value);
				CustomProperties properties = component as CustomProperties;
				if (this._name == "UserDefined")
				{
					properties.SetUserDefinedAttributes(stringFromValue);
				}
				else
				{
					bool flag = true;
					if ((this.IsDefaultValue(stringFromValue) && (!(properties.DataPointCustomProperties is DataPoint) || !((DataPoint)properties.DataPointCustomProperties).series.IsCustomPropertySet(this._name))) && properties.DataPointCustomProperties.IsCustomPropertySet(this._name))
					{
						properties.DataPointCustomProperties.DeleteCustomProperty(this._name);
						flag = false;
					}
					if (flag)
					{
						properties.DataPointCustomProperties[this._name] = stringFromValue;
					}
				}
				properties.DataPointCustomProperties.CustomProperties = properties.DataPointCustomProperties.CustomProperties;
				IChangeTracking tracking = component as IChangeTracking;
				if (tracking != null)
				{
					tracking.AcceptChanges();
				}
			}

			public virtual void ValidateValue(string attrName, object value)
			{
				if (this._customAttributeInfo != null)
				{
					bool flag = false;
					if (this._customAttributeInfo.MaxValue != null)
					{
						if (value.GetType() != this._customAttributeInfo.MaxValue.GetType())
						{
							throw new InvalidOperationException(SR.ExceptionCustomAttributeTypeOrMaximumPossibleValueInvalid(attrName));
						}
						if (!(value is float))
						{
							if (!(value is double))
							{
								if (!(value is int))
								{
									throw new InvalidOperationException(SR.ExceptionCustomAttributeTypeOrMinimumPossibleValueUnsupported(attrName));
								}
								if (((int)value) > ((int)this._customAttributeInfo.MaxValue))
								{
									flag = true;
								}
							}
							else if (((double)value) > ((double)this._customAttributeInfo.MaxValue))
							{
								flag = true;
							}
						}
						else if (((float)value) > ((float)this._customAttributeInfo.MaxValue))
						{
							flag = true;
						}
					}
					if (this._customAttributeInfo.MinValue != null)
					{
						if (value.GetType() != this._customAttributeInfo.MinValue.GetType())
						{
							throw new InvalidOperationException(SR.ExceptionCustomAttributeTypeOrMinimumPossibleValueInvalid(attrName));
						}
						if (!(value is float))
						{
							if (!(value is double))
							{
								if (!(value is int))
								{
									throw new InvalidOperationException(SR.ExceptionCustomAttributeTypeOrMinimumPossibleValueUnsupported(attrName));
								}
								if (((int)value) < ((int)this._customAttributeInfo.MinValue))
								{
									flag = true;
								}
							}
							else if (((double)value) < ((double)this._customAttributeInfo.MinValue))
							{
								flag = true;
							}
						}
						else if (((float)value) < ((float)this._customAttributeInfo.MinValue))
						{
							flag = true;
						}
					}
					if (flag)
					{
						if ((this._customAttributeInfo.MaxValue != null) && (this._customAttributeInfo.MinValue != null))
						{
							throw new InvalidOperationException(SR.ExceptionCustomAttributeMustBeInRange(attrName, this._customAttributeInfo.MinValue.ToString(), this._customAttributeInfo.MaxValue.ToString()));
						}
						if (this._customAttributeInfo.MinValue != null)
						{
							throw new InvalidOperationException(SR.ExceptionCustomAttributeMustBeBiggerThenValue(attrName, this._customAttributeInfo.MinValue.ToString()));
						}
						if (this._customAttributeInfo.MaxValue != null)
						{
							throw new InvalidOperationException(SR.ExceptionCustomAttributeMustBeMoreThenValue(attrName, this._customAttributeInfo.MaxValue.ToString()));
						}
					}
				}
			}
		}
	}
}

